// Decompiled on 周六 2月 22 19:31:49 CST 2025 with Zomboid Decompiler v0.1.3 using Vineflower.
package zombie.core.opengl;

import java.nio.ByteBuffer;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL12;
import org.lwjgl.opengl.GL13;
import zombie.core.SpriteRenderer;
import zombie.core.VBO.GLVertexBufferObject;
import zombie.core.VBO.IGLBufferObject;
import zombie.core.math.PZMath;

public final class VBOLines {
    private final int VERTEX_SIZE = 12;
    private final int COLOR_SIZE = 16;
    private final int ELEMENT_SIZE = 28;
    private final int COLOR_OFFSET = 12;
    private final int NUM_LINES = 128;
    private final int NUM_ELEMENTS = 256;
    private final int INDEX_SIZE = 2;
    private GLVertexBufferObject m_vbo;
    private GLVertexBufferObject m_ibo;
    private ByteBuffer m_elements;
    private ByteBuffer m_indices;
    private float m_lineWidth = 1.0F;
    private float m_dx = 0.0F;
    private float m_dy = 0.0F;
    private float m_dz = 0.0F;
    private int m_mode = 1;
    private boolean m_depth_test = false;

    private void create() {
        this.m_elements = BufferUtils.createByteBuffer(7168);
        this.m_indices = BufferUtils.createByteBuffer(512);
        IGLBufferObject iGLBufferObject = GLVertexBufferObject.funcs;
        this.m_vbo = new GLVertexBufferObject(7168L, iGLBufferObject.GL_ARRAY_BUFFER(), iGLBufferObject.GL_STREAM_DRAW());
        this.m_vbo.create();
        this.m_ibo = new GLVertexBufferObject(512L, iGLBufferObject.GL_ELEMENT_ARRAY_BUFFER(), iGLBufferObject.GL_STREAM_DRAW());
        this.m_ibo.create();
    }

    public void setOffset(float dx, float dy, float dz) {
        this.m_dx = dx;
        this.m_dy = dy;
        this.m_dz = dz;
    }

    public void addElement(float x, float y, float z, float r, float g, float b, float a) {
        if (this.isFull()) {
            this.flush();
        }

        if (this.m_elements == null) {
            this.create();
        }

        this.m_elements.putFloat(this.m_dx + x);
        this.m_elements.putFloat(this.m_dy + y);
        this.m_elements.putFloat(this.m_dz + z);
        this.m_elements.putFloat(r);
        this.m_elements.putFloat(g);
        this.m_elements.putFloat(b);
        this.m_elements.putFloat(a);
        short _short = (short)(this.m_indices.position() / 2);
        this.m_indices.putShort(_short);
    }

    public void addLine(float x0, float y0, float z0, float x1, float y1, float z1, float r, float g, float b, float a) {
        this.reserve(2);
        this.addElement(x0, y0, z0, r, g, b, a);
        this.addElement(x1, y1, z1, r, g, b, a);
    }

    public void addLine(
        float x0, float y0, float z0, float x1, float y1, float z1, float r0, float g0, float b0, float a0, float r1, float g1, float b1, float a1
    ) {
        this.reserve(2);
        this.addElement(x0, y0, z0, r0, g0, b0, a0);
        this.addElement(x1, y1, z1, r1, g1, b1, a1);
    }

    public void addTriangle(float x0, float y0, float z0, float x1, float y1, float z1, float x2, float y2, float z2, float r, float g, float b, float a) {
        this.reserve(3);
        this.addElement(x0, y0, z0, r, g, b, a);
        this.addElement(x1, y1, z1, r, g, b, a);
        this.addElement(x2, y2, z2, r, g, b, a);
    }

    public void addQuad(float x0, float y0, float x1, float y1, float z, float r, float g, float b, float a) {
        this.reserve(6);
        this.addTriangle(x0, y0, z, x1, y0, z, x0, y1, z, r, g, b, a);
        this.addTriangle(x1, y0, z, x1, y1, z, x0, y1, z, r, g, b, a);
    }

    boolean isFull() {
        if (this.m_elements == null) {
            return false;
        } else {
            return this.m_mode == 4 && this.m_elements.position() % 84 == 0 && this.m_elements.position() + 84 > 7168
                ? true
                : this.m_elements.position() == 7168;
        }
    }

    public void reserve(int numElements) {
        if (!this.hasRoomFor(numElements)) {
            this.flush();
        }
    }

    boolean hasRoomFor(int _int) {
        return this.m_elements == null || this.m_elements.position() / 28 + _int <= 256;
    }

    public void flush() {
        if (this.m_elements != null && this.m_elements.position() != 0) {
            this.m_elements.flip();
            this.m_indices.flip();
            GL13.glClientActiveTexture(33984);
            GL11.glDisableClientState(32888);
            this.m_vbo.bind();
            this.m_vbo.bufferData(this.m_elements);
            this.m_ibo.bind();
            this.m_ibo.bufferData(this.m_indices);
            GL11.glEnableClientState(32884);
            GL11.glEnableClientState(32886);
            GL11.glVertexPointer(3, 5126, 28, 0L);
            GL11.glColorPointer(4, 5126, 28, 12L);

            for (int int0 = 7; int0 >= 0; int0--) {
                GL13.glActiveTexture(33984 + int0);
                GL11.glDisable(3553);
            }

            if (this.m_depth_test) {
                GL11.glEnable(2929);
            } else {
                GL11.glDisable(2929);
            }

            GL11.glEnable(2848);
            GL11.glLineWidth(this.m_lineWidth);
            byte byte0 = 0;
            int int1 = this.m_elements.limit() / 28;
            byte byte1 = 0;
            int int2 = this.m_indices.limit() / 2;
            GL12.glDrawRangeElements(this.m_mode, byte0, byte0 + int1, int2 - byte1, 5123, (long)(byte1 * 2));
            this.m_vbo.bindNone();
            this.m_ibo.bindNone();
            this.m_elements.clear();
            this.m_indices.clear();
            GL11.glEnable(2929);
            GL11.glEnable(3553);
            GL11.glDisable(2848);
            GL13.glClientActiveTexture(33984);
            GL11.glEnableClientState(32888);
            SpriteRenderer.ringBuffer.restoreVBOs = true;
        }
    }

    public void setLineWidth(float width) {
        if (!PZMath.equal(this.m_lineWidth, width, 0.01F)) {
            this.flush();
            this.m_lineWidth = width;
        }
    }

    public void setMode(int mode) {
        assert mode == 1 || mode == 4;

        if (mode != this.m_mode) {
            this.flush();
            this.m_mode = mode;
        }
    }

    public void setDepthTest(boolean enabled) {
        if (enabled != this.m_depth_test) {
            this.flush();
            this.m_depth_test = enabled;
        }
    }
}
